using System;
using System.ComponentModel;
using InfiniTec;
using Microsoft.Exchange.WebServices.Data;

namespace CalendarSubscriptionApp
{
    [Serializable]
    public class AppointmentViewModel : INotifyPropertyChanged
    {
        private DateTime _DateTimeSent;
        private DateTime _End;
        [NonSerialized] private ExchangeConnector _ExchangeAdapter;
        private bool _HasAttachments;
        private string _Id;
        private Importance _Importance;
        private bool _IsAllDayEvent;
        private bool _IsCancelled;
        private bool _IsMeeting;
        private bool _IsRecurring;
        private bool _IsReminderSet;
        private string _Location;
        private bool _MeetingRequestWasSent;
        private DateTime? _ReminderDueBy;
        private DateTime _Start;
        private string _Subject;
        private AppointmentType _AppointmentType;
        private readonly string _AssociatedPrimaryEmailAddress;

        public AppointmentViewModel(Appointment model, ExchangeConnector exchangeAdapter, string associatedPrimaryEmailAddress)
        {
            if (model == null) throw new ArgumentNullException("model");
            if (exchangeAdapter == null) throw new ArgumentNullException("exchangeAdapter");
            UpdateModel(model);
            _ExchangeAdapter = exchangeAdapter;
            _AssociatedPrimaryEmailAddress = associatedPrimaryEmailAddress;
            _Id = model.Id.UniqueId;
        }

        public ItemId ItemId
        {
            get { return _Id; }
        }


        public bool MeetingRequestWasSent
        {
            get { return _MeetingRequestWasSent; }
            private set
            {
                if (_MeetingRequestWasSent == value) return;
                _MeetingRequestWasSent = value;
                PropertyChanged.Raise(this, "MeetingRequestWasSent");
            }
        }

        public Importance Importance
        {
            get { return _Importance; }
            set
            {
                if (_Importance == value) return;
                _Importance = value;
                PropertyChanged.Raise(this, "Importance");
            }
        }

        public DateTime DateTimeSent
        {
            get { return _DateTimeSent; }
            set
            {
                if (_DateTimeSent == value) return;
                _DateTimeSent = value;
                PropertyChanged.Raise(this, "DateTimeSent");
            }
        }

        public DateTime? ReminderDueBy
        {
            get { return _ReminderDueBy; }
            set
            {
                if (_ReminderDueBy == value) return;
                _ReminderDueBy = value;
                PropertyChanged.Raise(this, "ReminderDueBy");
            }
        }

        public bool IsReminderSet
        {
            get { return _IsReminderSet; }
            set
            {
                if (_IsReminderSet == value) return;
                _IsReminderSet = value;
                PropertyChanged.Raise(this, "IsReminderSet");
            }
        }


        public bool HasAttachments
        {
            get { return _HasAttachments; }
            set
            {
                if (_HasAttachments == value) return;
                _HasAttachments = value;
                PropertyChanged.Raise(this, "HasAttachments");
            }
        }

        public string Subject
        {
            get { return _Subject; }
            set
            {
                if (_Subject == value) return;
                _Subject = value;
                PropertyChanged.Raise(this, "Subject");
            }
        }

        public TimeSpan Duration
        {
            get { return End - Start; }
        }

        public DateTime Start
        {
            get { return _Start; }
            set
            {
                if (_Start == value) return;
                _Start = value;
                PropertyChanged.Raise(this, "Start");
                PropertyChanged.Raise(this, "Duration");
            }
        }

        public DateTime End
        {
            get { return _End; }
            set
            {
                if (_End == value) return;
                _End = value;
                PropertyChanged.Raise(this, "End");
                PropertyChanged.Raise(this, "Duration");
            }
        }

        public bool IsAllDayEvent
        {
            get { return _IsAllDayEvent; }
            set
            {
                if (_IsAllDayEvent == value) return;
                _IsAllDayEvent = value;
                PropertyChanged.Raise(this, "IsAllDayEvent");
            }
        }

        public string Location
        {
            get { return _Location; }
            set
            {
                if (_Location == value) return;
                _Location = value;
                PropertyChanged.Raise(this, "Location");
            }
        }

        public bool IsMeeting
        {
            get { return _IsMeeting; }
            set
            {
                if (_IsMeeting == value) return;
                _IsMeeting = value;
                PropertyChanged.Raise(this, "IsMeeting");
            }
        }

        public bool IsCancelled
        {
            get { return _IsCancelled; }
            set
            {
                if (_IsCancelled == value) return;
                _IsCancelled = value;
                PropertyChanged.Raise(this, "IsCancelled");
            }
        }

        public bool IsRecurring
        {
            get { return _IsRecurring; }
            set
            {
                if (_IsRecurring == value) return;
                _IsRecurring = value;
                PropertyChanged.Raise(this, "IsRecurring");
            }
        }

        [field: NonSerialized]
        public event PropertyChangedEventHandler PropertyChanged;

        internal void InitializeAfterDeserialization(ExchangeConnector exchangeAdapter)
        {
            if (exchangeAdapter == null) throw new ArgumentNullException("exchangeAdapter");
            _ExchangeAdapter = exchangeAdapter;
        }

        public void Refresh()
        {
            Appointment result = _ExchangeAdapter.RefreshAppointment(_Id, _AssociatedPrimaryEmailAddress);

            if (result != null)
            {
                UpdateModel(result);
            }
        }

        private void UpdateModel(Appointment appointment)
        {
            _Id = appointment.Id.UniqueId;

            MeetingRequestWasSent = appointment.MeetingRequestWasSent;
            Importance = appointment.Importance;
            DateTimeSent = appointment.DateTimeSent;
            IsReminderSet = appointment.IsReminderSet;
            if (IsReminderSet)
            {
                ReminderDueBy = appointment.ReminderDueBy;
            }
            else
            {
                ReminderDueBy = null;
            }
            HasAttachments = appointment.HasAttachments;
            Subject = appointment.Subject;
            Start = appointment.Start;
            End = appointment.End;
            IsAllDayEvent = appointment.IsAllDayEvent;
            Location = appointment.Location;
            AppointmentType = appointment.AppointmentType;
            IsMeeting = appointment.IsMeeting;
            if (IsMeeting)
            {
                IsCancelled = appointment.IsCancelled;
            }
        }

        public AppointmentType AppointmentType
        {
            get {
                return _AppointmentType;
            }
            set
            {
                if (_AppointmentType == value) return;
                _AppointmentType = value;
                PropertyChanged.Raise(this, "AppointmentType");
            }
        }
    }
}